package actions;

import java.awt.event.ActionEvent;
import java.util.StringTokenizer;
import java.util.concurrent.Semaphore;

import javax.swing.JOptionPane;

import parameters.RLM_Parameters;
import streaming.Call;
import streaming.CallManager;
import client.ClientApplication;
import client.ClientBindObject;
import client_gui.ClientWindow;
import client_gui_chat.ChatDialog;
import client_tree.User;

public class AudioCallAction extends RLMAbstractAction {

	public AudioCallAction(ClientWindow owner) {
		setActionOwner(owner);
		putValue(SMALL_ICON, loadIcon("images/audio_call.png"));
		putValue(NAME, "Audio Call");
		putValue(SHORT_DESCRIPTION, "Audio poziv");
		putValue(ACTION_COMMAND_KEY, "audio_action");
	}
	
	private ActionEvent event;
	private User user;
	private ClientBindObject cbo;
	private Call call;
	
	/*
	 * Obezbedjuje da se uspostavi TCP konekcija ka klijentu, pre nego sto se nastavi sa Audio call-om.
	 */
	private Semaphore tcpSemaphore = new Semaphore(1, true);
	
	
	@Override
	public void actionPerformed(ActionEvent e) {

		event = e;
		
		String actionCommand = event.getActionCommand();

		// ukoliko je akcija pokrenuta iz popup-a
		if ( actionCommand.equals("audio_action") ) {
			user = getActionOwner().getSelectedUser();
			
		}
		// ukoliko je akcija pokrenuta dugmetom iz chat dijaloga
		else {
			user = getActionOwner().getApplicaton().getClientModel().getOnlineModel().getUserByUsername(actionCommand);
		}

		if ( user == null ) {
			return;
		}
		
		cbo = ClientApplication.clientBinding.get(user.getUsername());
		
		try {
			tcpSemaphore.acquire();
		} catch (InterruptedException e2) {
			e2.printStackTrace();
		}
		
		if ( cbo == null || cbo.getConnection() == null ) {
			new Thread(new Runnable() {
				@Override
				public void run() {

					getActionOwner().getActionManager().getSendMessageAction().actionPerformed(event);

					tcpSemaphore.release();
				}
			}).start();
		}
		else {
			if ( cbo.getDialog() == null ) {
				ChatDialog cd = new ChatDialog(getActionOwner(), user);
				cbo.setChatDialog(cd);
				cbo.setChatDialogConnection(cbo.getConnection());
				cbo.getDialog().setVisible(true);
			}
			
			tcpSemaphore.release();
		}
	
		
		try {
			tcpSemaphore.acquire();
		} catch (InterruptedException e2) {
			e2.printStackTrace();
		}

		cbo = ClientApplication.clientBinding.get(user.getUsername());
		
		if ( cbo == null ) {
			tcpSemaphore.release();
			return;
		}
		

		call = cbo.getCall();

		if ( call != null ) {
			if ( call.isAudioEstablished() || call.isVideoEstablished() ) {
				cbo.getDialog().getStreamingPanel().hideUserCallingProgress();
				JOptionPane.showMessageDialog(cbo.getDialog(), "Audio call already established !", "Audio Call", JOptionPane.INFORMATION_MESSAGE);
				tcpSemaphore.release();
				return;
			}
			else if ( call.isAudioRequested() || call.isVideoRequested() ) {
				JOptionPane.showMessageDialog(cbo.getDialog(), "Audio call already requested !", "Audio Call", JOptionPane.INFORMATION_MESSAGE);
				tcpSemaphore.release();
				return;
			}
		}

		tcpSemaphore.release();
		
		new Thread(new Runnable() {
			@Override
			public void run() {

				if ( cbo.getDialog() != null )
					cbo.getDialog().getStreamingPanel().showUserCallingProgress();
				
				call = CallManager.createCall();
				
				cbo.getDialog().getStreamingPanel().getPeerVolumeSlider().addChangeListener(call.getAudioControl());
				cbo.getDialog().getStreamingPanel().getPeerMute().addChangeListener(call.getAudioControl());
				
				StringBuffer messageBuffer = new StringBuffer();
				messageBuffer.append("CALL_REQUEST ");
				messageBuffer.append(getActionOwner().getApplicaton().getClientUser().getUsername());
				messageBuffer.append(" A ");
				messageBuffer.append(call.isAudioAvailable());
				messageBuffer.append(" ");
				messageBuffer.append(RLM_Parameters.getAudioPort());

				
				call.setAudioRequested(true);
				cbo.setCall(call);

				
				System.out.println("REQUEST: " + messageBuffer.toString().trim());
				
				cbo.getConnection().setMessage(CALL_REQUEST, messageBuffer.toString().trim());

				String response = cbo.getConnection().buffers[CALL_REQUEST].read();

				// parsirati odgovor
				System.out.println(response);
				
				if ( cbo.getDialog() != null )
					cbo.getDialog().getStreamingPanel().hideUserCallingProgress();
				
				StringTokenizer tokens = new StringTokenizer(response);
				tokens.nextToken();		// preskace CLIENT_RESPONSE
				
				String streamingType;
				int audioPort = 0;
				int videoPort = 0;
				boolean isAudioAvailable = false;
				boolean isVideoAvailable = false;
				boolean audioRequest = false;
				boolean videoRequest = false;
				
				try {
					streamingType = tokens.nextToken();
				}
				catch (Exception ex) {
					return;
				}
				
				if ( streamingType.equals("V") ) {
					
					isVideoAvailable = Boolean.parseBoolean(tokens.nextToken());
					
					try {
						videoPort = Integer.parseInt(tokens.nextToken());
						videoRequest = true;
					}
					catch (Exception ex) {
						videoRequest = false;
//						return false;
					}
					
					streamingType = tokens.nextToken();
				}
				
				if ( streamingType.equals("A") ) {
					
					isAudioAvailable = Boolean.parseBoolean(tokens.nextToken());
					
					try {
						audioPort = Integer.parseInt(tokens.nextToken());
						audioRequest = true;
					}
					catch (Exception ex) {
						audioRequest = false;
					}
				}
				else {
					cbo.getCall().hangUpCall();
					cbo.getDialog().getStreamingPanel().removeListeners();
					cbo.setCall(null);
					return;
				}
				
				// end of parsing
				
				boolean flag = false;
				if(cbo.isConnectionActive() && (audioRequest || videoRequest)){
					flag = call.initializeAudioCall(cbo.getConnection().getClientAddress(), audioPort, call.getVideoStatus(isAudioAvailable), false);
					call.setAudioEstablished(flag);
					if(videoRequest && isVideoAvailable){
						flag = call.initializeVideoCall(cbo.getConnection().getClientAddress(), videoPort, call.getVideoStatus(isVideoAvailable), true);
						call.setVideoEstablished(flag);
					}
				}
//				if ( videoRequest ) {
//					// pokrenuti video konverzaciju
//					boolean flag = false;
//					if ( cbo.isConnectionActive() )
//						flag = call.initializeVideoCall(cbo.getConnection().getClientAddress(), videoPort, call.getVideoStatus(isVideoAvailable), true);
//					call.setVideoEstablished(flag);
//				}
//				else if ( audioRequest ) {
//					if ( isVideoAvailable ) {
//						// pokrenuti video konverzaciju
//						boolean flag = false;
//						if ( cbo.isConnectionActive() )
//							flag = call.initializeVideoCall(cbo.getConnection().getClientAddress(), videoPort, call.getVideoStatus(isVideoAvailable), true);
//						call.setVideoEstablished(flag);
//					}
//					else if ( isAudioAvailable ) {
//						// samo audio
//						boolean flag = false;
//						if ( cbo.isConnectionActive() )
//							flag = call.initializeAudioCall(cbo.getConnection().getClientAddress(), audioPort, call.getVideoStatus(isAudioAvailable), false);
//						call.setAudioEstablished(flag);
//					}
//				}
				
				if ( call.isVideoEstablished() || call.isAudioEstablished() ) {
					call.start();
				}
			}
		}).start();

	}
	
}
